import express, { Request, Response } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
import compression from 'compression';
import rateLimit from 'express-rate-limit';
import swaggerJsdoc from 'swagger-jsdoc';
import swaggerUi from 'swagger-ui-express';
import path from 'path';

import { errorHandler } from './middleware/errorHandler';
import { notFoundHandler } from './middleware/notFoundHandler';
import { languageDetector, languageInfo } from './middleware/languageDetector';
import { operationLogMiddleware } from './middleware/operationLog';
import { logger } from './utils/logger';
import { connectDatabase } from './config/database';
import { ConfigUtils, initializeConfig } from './config';

// 路由配置导入
import { configureRoutes, getRouteInfo } from './routes/router';

// 初始化配置
const appConfig = initializeConfig();

const app = express();
const PORT = appConfig.server.port;

// 安全中间件
app.use(helmet());

// 跨域配置
app.use(cors({
  origin: appConfig.server.corsOrigin,
  credentials: true
}));

// 请求限流
const limiter = rateLimit({
  windowMs: ConfigUtils.getRateLimitConfig().windowMs,
  max: ConfigUtils.getRateLimitConfig().max,
  message: {
    error: '请求过于频繁，请稍后再试'
  }
});
app.use('/api/', limiter);

// 压缩响应
app.use(compression());

// 日志中间件
app.use(morgan('combined', {
  stream: {
    write: (message: string) => logger.info(message.trim())
  }
}));

// 语言检测中间件
app.use(languageDetector);
app.use(languageInfo);

// 操作日志中间件
app.use(operationLogMiddleware);

// 解析请求体
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));

// Swagger API文档配置
const swaggerOptions = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'OffGrid 管理系统 API',
      version: '1.0.0',
      description: '基于 TypeScript + Express + MySQL + Prisma 构建的管理系统 API',
      contact: {
        name: 'API Support',
        email: 'support@offgrid.com'
      }
    },
    servers: [
      {
        url: `http://${appConfig.server.host}:${PORT}`,
        description: `${appConfig.server.environment} 服务器`
      }
    ],
    components: {
      securitySchemes: {
        bearerAuth: {
          type: 'http',
          scheme: 'bearer',
          bearerFormat: 'JWT'
        }
      },
      schemas: {
        SystemConfig: {
          type: 'object',
          properties: {
            id: {
              type: 'integer',
              description: '配置ID',
              example: 1
            },
            key: {
              type: 'string',
              description: '配置键（唯一标识）',
              example: 'site_name'
            },
            value: {
              type: 'string',
              description: '配置值',
              example: '我的系统'
            },
            description: {
              type: 'string',
              description: '配置描述',
              example: '网站名称'
            },
            type: {
              type: 'string',
              enum: ['STRING', 'NUMBER', 'BOOLEAN', 'JSON'],
              description: '配置类型',
              example: 'STRING'
            },
            createdAt: {
              type: 'string',
              format: 'date-time',
              description: '创建时间',
              example: '2024-01-01T00:00:00.000Z'
            },
            updatedAt: {
              type: 'string',
              format: 'date-time',
              description: '更新时间',
              example: '2024-01-01T00:00:00.000Z'
            }
          },
          required: ['id', 'key', 'value', 'type', 'createdAt', 'updatedAt']
        },
        Pagination: {
          type: 'object',
          properties: {
            page: {
              type: 'integer',
              description: '当前页码',
              example: 1
            },
            limit: {
              type: 'integer',
              description: '每页数量',
              example: 20
            },
            total: {
              type: 'integer',
              description: '总记录数',
              example: 100
            },
            totalPages: {
              type: 'integer',
              description: '总页数',
              example: 5
            },
            hasNext: {
              type: 'boolean',
              description: '是否有下一页',
              example: true
            },
            hasPrev: {
              type: 'boolean',
              description: '是否有上一页',
              example: false
            }
          },
          required: ['page', 'limit', 'total', 'totalPages', 'hasNext', 'hasPrev']
        },
        User: {
          type: 'object',
          properties: {
            id: {
              type: 'integer',
              description: '用户ID',
              example: 1
            },
            username: {
              type: 'string',
              description: '用户名',
              example: 'admin'
            },
            email: {
              type: 'string',
              description: '邮箱',
              example: 'admin@example.com'
            },
            realName: {
              type: 'string',
              description: '真实姓名',
              example: '管理员'
            },
            phone: {
              type: 'string',
              description: '手机号',
              example: '13800138000'
            },
            status: {
              type: 'string',
              enum: ['ACTIVE', 'INACTIVE', 'BANNED'],
              description: '用户状态',
              example: 'ACTIVE'
            },
            avatar: {
              type: 'string',
              description: '头像URL',
              example: '/uploads/avatar.jpg'
            },
            lastLoginAt: {
              type: 'string',
              format: 'date-time',
              description: '最后登录时间',
              example: '2024-01-01T00:00:00.000Z'
            },
            createdAt: {
              type: 'string',
              format: 'date-time',
              description: '创建时间',
              example: '2024-01-01T00:00:00.000Z'
            },
            updatedAt: {
              type: 'string',
              format: 'date-time',
              description: '更新时间',
              example: '2024-01-01T00:00:00.000Z'
            }
          },
          required: ['id', 'username', 'email', 'status', 'createdAt', 'updatedAt']
        },
        Role: {
          type: 'object',
          properties: {
            id: {
              type: 'integer',
              description: '角色ID',
              example: 1
            },
            name: {
              type: 'string',
              description: '角色名称',
              example: '管理员'
            },
            description: {
              type: 'string',
              description: '角色描述',
              example: '系统管理员'
            },
            status: {
              type: 'string',
              enum: ['ACTIVE', 'INACTIVE'],
              description: '角色状态',
              example: 'ACTIVE'
            },
            createdAt: {
              type: 'string',
              format: 'date-time',
              description: '创建时间',
              example: '2024-01-01T00:00:00.000Z'
            },
            updatedAt: {
              type: 'string',
              format: 'date-time',
              description: '更新时间',
              example: '2024-01-01T00:00:00.000Z'
            }
          },
          required: ['id', 'name', 'status', 'createdAt', 'updatedAt']
        },
        Permission: {
          type: 'object',
          properties: {
            id: {
              type: 'integer',
              description: '权限ID',
              example: 1
            },
            name: {
              type: 'string',
              description: '权限名称',
              example: '用户查看'
            },
            code: {
              type: 'string',
              description: '权限代码',
              example: 'user:read'
            },
            description: {
              type: 'string',
              description: '权限描述',
              example: '查看用户信息'
            },
            module: {
              type: 'string',
              description: '所属模块',
              example: 'USER'
            },
            createdAt: {
              type: 'string',
              format: 'date-time',
              description: '创建时间',
              example: '2024-01-01T00:00:00.000Z'
            },
            updatedAt: {
              type: 'string',
              format: 'date-time',
              description: '更新时间',
              example: '2024-01-01T00:00:00.000Z'
            }
          },
          required: ['id', 'name', 'code', 'module', 'createdAt', 'updatedAt']
        },
        OperationLog: {
          type: 'object',
          properties: {
            id: {
              type: 'integer',
              description: '日志ID',
              example: 1
            },
            action: {
              type: 'string',
              description: '操作动作',
              example: '用户创建'
            },
            resource: {
              type: 'string',
              description: '操作资源',
              example: '用户管理'
            },
            resourceId: {
              type: 'string',
              description: '资源ID',
              example: '123'
            },
            details: {
              type: 'object',
              description: '操作详情',
              example: { userId: 1, username: 'admin' }
            },
            ipAddress: {
              type: 'string',
              description: 'IP地址',
              example: '192.168.1.1'
            },
            userAgent: {
              type: 'string',
              description: '用户代理',
              example: 'Mozilla/5.0...'
            },
            createdAt: {
              type: 'string',
              format: 'date-time',
              description: '创建时间',
              example: '2024-01-01T00:00:00.000Z'
            },
            user: {
              $ref: '#/components/schemas/User'
            }
          },
          required: ['id', 'action', 'resource', 'createdAt']
        },
        ApiResponse: {
          type: 'object',
          properties: {
            success: {
              type: 'boolean',
              description: '请求是否成功',
              example: true
            },
            code: {
              type: 'integer',
              description: '响应状态码',
              example: 200
            },
            message: {
              type: 'string',
              description: '响应消息',
              example: '操作成功'
            },
            data: {
              type: 'object',
              description: '响应数据'
            },
            timestamp: {
              type: 'string',
              format: 'date-time',
              description: '响应时间戳',
              example: '2024-01-01T00:00:00.000Z'
            }
          },
          required: ['success', 'code', 'message', 'timestamp']
        },
        ErrorResponse: {
          type: 'object',
          properties: {
            success: {
              type: 'boolean',
              description: '请求是否成功',
              example: false
            },
            code: {
              type: 'integer',
              description: '错误状态码',
              example: 400
            },
            message: {
              type: 'string',
              description: '错误消息',
              example: '请求参数错误'
            },
            errors: {
              type: 'array',
              items: {
                type: 'object',
                properties: {
                  field: {
                    type: 'string',
                    description: '错误字段',
                    example: 'username'
                  },
                  message: {
                    type: 'string',
                    description: '错误消息',
                    example: '用户名不能为空'
                  }
                }
              },
              description: '详细错误信息'
            },
            timestamp: {
              type: 'string',
              format: 'date-time',
              description: '响应时间戳',
              example: '2024-01-01T00:00:00.000Z'
            }
          },
          required: ['success', 'code', 'message', 'timestamp']
        }
      }
    },
    security: [
      {
        bearerAuth: []
      }
    ]
  },
  apis: ['./src/routes/*.ts', './src/routes/client/*.ts', './src/routes/admin/*.ts', './src/models/*.ts']
};

const swaggerSpec = swaggerJsdoc(swaggerOptions);

// API文档路由（仅在开发环境或明确启用时显示）
if (ConfigUtils.isSwaggerEnabled()) {
  app.use(ConfigUtils.getSwaggerPath(), swaggerUi.serve, swaggerUi.setup(swaggerSpec));
  logger.info(`📚 Swagger 文档已启用: http://${appConfig.server.host}:${PORT}${ConfigUtils.getSwaggerPath()}`);
}

// 健康检查
app.get('/health', (_req: Request, res: Response) => {
  res.json({
    status: 'OK',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    environment: appConfig.server.environment
  });
});

// 静态文件服务
app.use('/uploads', express.static(path.join(__dirname, '../uploads')));

// 配置API路由
const apiRouter = configureRoutes();
app.use('/', apiRouter);

// 404处理
app.use(notFoundHandler);

// 错误处理中间件
app.use(errorHandler);

// 启动服务器
async function startServer() {
  try {
    // 验证配置
    const validation = ConfigUtils.validateConfig();
    if (!validation.isValid) {
      logger.error('配置验证失败:', validation.errors);
      process.exit(1);
    }

    // 记录配置摘要
    logger.info('应用配置:', ConfigUtils.getSafeConfig());

    // 连接数据库
    await connectDatabase();
    logger.info('数据库连接成功');

    // 启动服务器
    app.listen(PORT, appConfig.server.host, () => {
      logger.info(`🚀 服务器启动成功！`);
      logger.info(`📍 运行环境: ${appConfig.server.environment}`);
      logger.info(`🌐 服务器地址: http://${appConfig.server.host}:${PORT}`);
      logger.info(`📚 API文档地址: http://${appConfig.server.host}:${PORT}/api-docs`);
      logger.info(`💚 健康检查地址: http://${appConfig.server.host}:${PORT}/health`);
      // 显示路由信息
      const routeInfo = getRouteInfo();
      logger.info('📱 客户端API路由:', routeInfo.client);
      logger.info('⚙️ 管理后台API路由:', routeInfo.admin);
      logger.info('🔄 兼容性API路由:', routeInfo.compatibility);
      
      if (ConfigUtils.isDevelopment()) {
        logger.info('🔧 开发模式已启用');
      }
    });
  } catch (error) {
    logger.error('服务器启动失败:', error);
    process.exit(1);
  }
}

// 优雅关闭
process.on('SIGTERM', () => {
  logger.info('收到 SIGTERM 信号，正在关闭服务器...');
  process.exit(0);
});

process.on('SIGINT', () => {
  logger.info('收到 SIGINT 信号，正在关闭服务器...');
  process.exit(0);
});

// 启动服务器
startServer();

export default app; 